package com.gzs.learn.payment.api.controller;

import cn.felord.payment.wechat.v3.model.ResponseSignVerifyParams;
import com.gzs.learn.common.util.JsonUtil;
import com.gzs.learn.common.util.ServletUtil;
import com.gzs.learn.inf.BaseResponseDto;
import com.gzs.learn.payment.inf.exception.PaymentException;
import com.gzs.learn.payment.pay.*;
import com.gzs.learn.payment.pay.context.PaymentCallbackContext;
import com.gzs.learn.payment.pay.context.RefundCallbackContext;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

/**
 * @author zhisong.guan
 */
@RestController
@RequestMapping("/payment/callback")
@Slf4j
@RequiredArgsConstructor
public class PaymentCallbackController {

    public static final String OPERATOR = "payment_callback";

    public static final String OPERATOR_REFUND = "payment_callback_refund";

    private final PaymentDomain paymentDomain;

    @PostMapping("alipay/{serial}")
    public String alipayCallback(@PathVariable("serial") Long serial) {
        return null;
    }

    /**
     * v2 微信支付
     */
    @PostMapping("wechat/{serial}")
    public String wechatCallback(@PathVariable("serial") Long serial) {
        log.info("recv wechat callback");
        return null;
    }

    /**
     * v3 微信支付回调
     */
    @PostMapping("wechat/v3/{serial}")
    public String wechatV3Callback(@PathVariable("serial") Long serial,
            @RequestHeader("Wechatpay-Serial") String wechatpaySerial,
            @RequestHeader("Wechatpay-Signature") String wechatpaySignature,
            @RequestHeader("Wechatpay-Timestamp") String wechatpayTimestamp,
            @RequestHeader("Wechatpay-Nonce") String wechatpayNonce) throws Exception {
        log.info("recv wechat v3 callback,serial:{},wechatpaySerial:{}", serial, wechatpaySerial);
        PaymentContext<ContextBase> paymentContext = new PaymentContext<>();
        PaymentCallbackContext contextObject = new PaymentCallbackContext();
        contextObject.setSerial(serial);
        contextObject.setOperator(OPERATOR);
        contextObject.setOperatorIp(ServletUtil.getClientIp());

        ResponseSignVerifyParams params = new ResponseSignVerifyParams();
        params.setWechatpayNonce(wechatpayNonce);
        params.setWechatpaySerial(wechatpaySerial);
        params.setWechatpaySignature(wechatpaySignature);
        params.setWechatpayTimestamp(wechatpayTimestamp);
        params.setBody(ServletUtil.getRequestBodyAsString());
        contextObject.setWechatCallBackData(params);

        paymentContext.setActionEnum(ActionEnum.PAYMENT_CALLBACK);
        paymentContext.setPaymentTypeEnum(PaymentTypeEnum.WECHAT);
        paymentContext.setContextObject(contextObject);
        BaseResponseDto<?> result = paymentDomain.execute(paymentContext);
        if (BaseResponseDto.isSuccess(result)) {
            return JsonUtil.toJSONString(result.getData());
        } else {
            throw new PaymentException(result == null ? "payment callback fail" : result.getMsg());
        }
    }

    /**
     * v3 微信退款回调
     */
    @PostMapping("wechat/v3/{refund_serial}")
    @ResponseBody
    public String wechatV3RefundCallback(@PathVariable("refund_serial") Long refundSerial,
            @RequestHeader("Wechatpay-Serial") String wechatpaySerial,
            @RequestHeader("Wechatpay-Signature") String wechatpaySignature,
            @RequestHeader("Wechatpay-Timestamp") String wechatpayTimestamp,
            @RequestHeader("Wechatpay-Nonce") String wechatpayNonce) throws Exception {
        log.info("recv wechat v3 refund callback,refundSerial:{},wechatpaySerial:{}", refundSerial, wechatpaySerial);
        PaymentContext<ContextBase> paymentContext = new PaymentContext<>();
        RefundCallbackContext context = new RefundCallbackContext();
        context.setRefundSerial(refundSerial);
        context.setOperator(OPERATOR_REFUND);
        context.setOperatorIp(ServletUtil.getClientIp());
        ResponseSignVerifyParams params = new ResponseSignVerifyParams();
        params.setWechatpayNonce(wechatpayNonce);
        params.setWechatpaySerial(wechatpaySerial);
        params.setWechatpaySignature(wechatpaySignature);
        params.setWechatpayTimestamp(wechatpayTimestamp);
        params.setBody(ServletUtil.getRequestBodyAsString());
        context.setWechatCallBackData(params);

        paymentContext.setActionEnum(ActionEnum.REFUND_CALLBACK);
        paymentContext.setPaymentTypeEnum(PaymentTypeEnum.WECHAT);
        paymentContext.setContextObject(context);
        BaseResponseDto<?> result = paymentDomain.execute(paymentContext);
        if (BaseResponseDto.isSuccess(result)) {
            return JsonUtil.toJSONString(result.getData());
        } else {
            throw new PaymentException(result == null ? "payment refund callback fail" : result.getMsg());
        }
    }
}
